package cn.hiapi.shop.api;

import cn.hiapi.basic.ResponseEntity;
import cn.hiapi.basic.controller.BasicCurdController;
import cn.hiapi.basic.entity.BasicEntity;
import cn.hiapi.basic.exception.BasicException;
import cn.hiapi.basic.jpa.pageable.PageRequest;
import cn.hiapi.basic.jpa.pageable.QueryWrapper;
import cn.hiapi.basic.security.TokenGet;
import cn.hiapi.basic.token.Token;
import cn.hiapi.interfaces.DispatchContext;
import cn.hiapi.interfaces.config.IConfigService;
import cn.hiapi.interfaces.finance.IAssetsService;
import cn.hiapi.interfaces.finance.IPaymentService;
import cn.hiapi.interfaces.finance.model.AmountModel;
import cn.hiapi.interfaces.finance.model.PayTypes;
import cn.hiapi.interfaces.finance.model.RechargeModel;
import cn.hiapi.interfaces.user.IUserService;
import cn.hiapi.shop.query.ActivityQuery;
import cn.hiapi.shop.service.product.ProductNumService;
import cn.hiapi.shop.service.shop.ShopLinkUserService;
import cn.hiapi.shop.vo.ActivityInfoVo;
import cn.hiapi.shop.vo.ApplyRecordDownload;
import cn.hiapi.shopkeeper.consts.AppConst;
import cn.hiapi.shopkeeper.entity.activity.*;
import cn.hiapi.shopkeeper.entity.order.ActivityLotteryOrder;
import cn.hiapi.shopkeeper.entity.order.ActivityOrder;
import cn.hiapi.shopkeeper.enums.ActivityType;
import cn.hiapi.shopkeeper.service.ActivityNumber;
import cn.hiapi.shopkeeper.service.Shopkeeper;
import cn.hiapi.shopkeeper.service.activity.*;
import cn.hiapi.shopkeeper.service.order.ActivityLotteryOrderService;
import cn.hiapi.shopkeeper.service.order.ActivityOrderService;
import cn.hiapi.shopkeeper.service.shopkeeper.ActivityPreviewService;
import cn.hiapi.shopkeeper.service.shopkeeper.ShopUserService;
import cn.hiapi.utils.DateUtils;
import cn.hiapi.utils.JsonUtils;
import cn.hiapi.utils.RandomUtils;
import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Sort;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author AdinZ
 * @date 2022/12/12 22:30
 */
@RestController("shopkeeperActivityController")
@RequestMapping("/shop/activity")
public class ActivityController extends BasicCurdController<Activity, Long, ActivityInfoVo, ActivityQuery> {


    protected ActivityController(ActivityService basicService, DispatchContext dispatchContext) {
        super(basicService, dispatchContext);
    }

    @Override
    public ActivityQuery setQuery(ActivityQuery query) {
        Token<Object> token = TokenGet.get();
        this.dispatchContext.getServiceOne(ShopLinkUserService.class).verifyShop(token.getFid(), query.getShopId());
        return super.setQuery(query);
    }

    @Override
    public List<ActivityInfoVo> toListVo(List<Activity> list, String[] fields) {

        return list.stream().map(e -> this.toData(e, fields)).collect(Collectors.toList());
    }

    @Override
    public ActivityInfoVo toData(Activity e, String[] fields) {
        ActivityInfoVo vo = new ActivityInfoVo();
        e.copy(vo);
        vo.setStatus(e.getStatus());
        if (e.getCid() > 0) {
            ActivityCategory category = this.dispatchContext.getServiceOne(ActivityCategoryService.class).get(e.getCid());
            if (category != null) vo.setCategory(category.getName());
        }
        BasicEntity basic = this.dispatchContext.getServiceOne(ActivityFactory.class).get(e.getType()).getByAid(e.getId());
        if (basic != null) {
            JSONObject expand = JSON.parseObject(basic.toJSONString());
            if (e.getType() == ActivityType.LOTTERY || e.getType() == ActivityType.LOTTERY_AD) {
                expand.put("items", this.dispatchContext.getServiceOne(ActivityLotteryItemService.class).findByAid(e.getId()));
                if (expand.getIntValue("template") == 1) {
                    vo.setThumb("https://shopkeeper-sx.oss-cn-hangzhou.aliyuncs.com/upload/2023-03-08/3068552153555333120.png");
                } else {
                    vo.setThumb("https://shopkeeper-sx.oss-cn-hangzhou.aliyuncs.com/upload/2023-03-08/3068552240541003776.png");
                }
            } else if (e.getType() == ActivityType.VOTE) {
                List<ActivityVoteOther> others = this.dispatchContext.getServiceOne(ActivityVoteOtherService.class).findByAid(e.getId());
                List<ActivityVoteItem> items = this.dispatchContext.getServiceOne(ActivityVoteItemService.class).findByAid(e.getId());
                expand.put("others", others);
                expand.put("items", items);
            } else if (e.getType() == ActivityType.SOLITAIRE) {
                expand.put("items", this.dispatchContext.getServiceOne(ActivitySolitaireItemService.class).listByAid(e.getId()));
            }
            vo.setExpand(expand);
        }

        ActivityOther other = this.dispatchContext.getServiceOne(ActivityOtherService.class).getByAid(e.getId());
        if (other != null)
            vo.setOther(JSON.parseObject(other.toJSONString()));


        ActivityNumber.Total total = this.dispatchContext.getServiceOne(ActivityNumber.class).get(e.getType(), e.getId());
        vo.setSales(total.getSales());
        vo.setParticipate(total.getParticipate());
        return vo;
    }

    @Override
    @Transactional
    public Activity parseData(ActivityInfoVo data) {
        if (data.getType() == null)
            throw new BasicException("活动类型错误");
        if (StringUtils.isEmpty(data.getTitle())) {
            throw new BasicException("活动标题错误");
        }
        if (data.getShopId() <= 0) throw new BasicException("缺少参数 shopId");
        Token<Object> token = TokenGet.get();
        this.dispatchContext.getServiceOne(ShopLinkUserService.class).verifyShop(token.getFid(), data.getShopId());

//        if (data.getCid() < 1000) throw new BasicException("活动所属分类错误");

        if (data.getStartTime() < 100000)
            throw new BasicException("活动开始时间错误");
        if (data.getEndTime() < 10000)
            throw new BasicException("活动结束时间错误");

        if (data.getUseStart() < 100000 || data.getUseEnd() < 10000)
            throw new BasicException("兑换时间错误");

        if (data.getExpand() == null) {
            throw new BasicException("扩展参数错误");
        }
        ActivityOther other;
        if (data.getOther() != null) other = data.getOther().toJavaObject(ActivityOther.class);
        else other = new ActivityOther();
        if (other.getId() != null) other.setId(null);
      /*  if (other.getShare() == 1) {
            AmountModel amount = this.dispatchContext.getServiceOne(IAssetsService.class).getAmount(data.getShopId(), AppConst.FINANCE_AMOUNT_MONEY);
            if (amount.getAmount().compareTo(BigDecimal.valueOf(300)) < 0)
                throw new BasicException("余额低于300无法启用分享有奖");
            if (other.getShareAmount().compareTo(BigDecimal.ZERO) <= 0)
                throw new BasicException("分享有奖金额错误");
            if (other.getShareTotal() < 1) throw new BasicException("奖励总分数不能小于1");
        }*/

        if (data.getId() != null) {
            Activity source = this.dispatchContext.getServiceOne(ActivityService.class).get(data.getId());
            if (source != null) {
                if (source.getStatus() == 2 || source.getEndTime() < System.currentTimeMillis())
                    throw new BasicException("活动已结束,无法再次编辑");
            }
        }

        Activity activity = data.copy(new Activity());
        if (activity.getType() == ActivityType.LOTTERY || activity.getType() == ActivityType.LOTTERY_AD) {
            if (data.getExpand().getIntValue("template") == 1) {
                activity.setThumb("https://shopkeeper-sx.oss-cn-hangzhou.aliyuncs.com/upload/2023-02-22/3063412746217123840.png");
            } else {
                activity.setThumb("https://shopkeeper-sx.oss-cn-hangzhou.aliyuncs.com/upload/2023-02-22/3063413541310361600.png");
            }
        }
        if (activity.getStartTime() < System.currentTimeMillis()) {
            activity.setStatus(1);
        }
        if (activity.getEndTime() < System.currentTimeMillis()) activity.setStatus(2);
        return activity;
    }

    @Override
    @Transactional
    public void saveCallback(ActivityInfoVo data, Activity activity) {
        JSONObject object = JSON.parseObject(JSON.toJSONString(data.getExpand()));
        object.put("shopId", data.getShopId());
        object.remove("id");
        this.dispatchContext.getServiceOne(ActivityFactory.class).get(data.getType()).deleteByAid(activity.getId());
        this.dispatchContext.getServiceOne(ActivityFactory.class)
                .get(data.getType()).saveExpand(activity.getId(), object);
        //删除旧的其他设置
        this.dispatchContext.getServiceOne(ActivityOtherService.class).deleteByAid(activity.getId());
        final ActivityOther other;
        if (data.getOther() != null) other = data.getOther().toJavaObject(ActivityOther.class);
        else other = new ActivityOther();
        if (other.getId() != null) other.setId(null);
        other.setAid(activity.getId());
        other.setShopId(activity.getShopId());
        //保存新的其他设置
        this.dispatchContext.getServiceOne(ActivityOtherService.class).save(other);
    }


    @ApiOperation(value = "分类列表", notes = "分类列表", nickname = "AdinZ")
    @GetMapping("/category")
    public ResponseEntity<List> category() {
        List<ActivityCategory> list = this.dispatchContext.getServiceOne(ActivityCategoryService.class).findList(new QueryWrapper().eq("status", 1), Sort.by(Sort.Direction.DESC, "sort"));
        return toSuccess(list);
    }

    @Override
    public ResponseEntity deleteData(Long[] id) {
        Token<Object> token = TokenGet.get();
        List<Activity> list = this.basicService.findList(id);
        if (list.isEmpty()) return toError("id不存在");
        list.forEach(activity -> this.dispatchContext.getServiceOne(ShopLinkUserService.class).verifyShop(token.getFid(), activity.getShopId()));
        return super.deleteData(id);
    }


    @ApiOperation(value = "更新活动状态", notes = "更新活动状态", nickname = "AdinZ")
    @GetMapping("/update-status")
    public ResponseEntity updateStatus(@RequestParam("id") long id, @RequestParam("status") int status) {

        Activity activity = basicService.get(id);
        if (activity.getId() == null) return toError("不存在");
        Token<Object> token = TokenGet.get();
        this.dispatchContext.getServiceOne(ShopLinkUserService.class).verifyShop(token.getFid(), activity.getShopId());

        if(activity.getStatus()!=1)return toError("活动状态错误");
        long millis = System.currentTimeMillis();
        activity.setEndTime(millis);
        activity.setUpdated(millis);
        this.basicService.save(activity);
        return toSuccess();
    }


    @ApiOperation(value = "统计数据", notes = "统计数据", nickname = "AdinZ")
    @GetMapping("/data-view")
    public ResponseEntity data(@RequestParam("shopId") long shopId, @RequestParam("id") long id) {
        Activity activity = basicService.get(id);
        if (activity == null || activity.getShopId() != shopId) return toError("活动不存在");
        Token<Object> token = TokenGet.get();
        this.dispatchContext.getServiceOne(ShopLinkUserService.class).verifyShop(token.getFid(), shopId);

        JsonUtils.Builder builder = JsonUtils.builder();
        long order = this.dispatchContext.getServiceOne(ActivityOrderService.class).count(new QueryWrapper().eq("aid", activity.getId()));
        builder.put("order", order); //订单总数
        if (activity.getType() == ActivityType.LOTTERY_AD) {
            long lottery = this.dispatchContext.getServiceOne(ActivityLotteryOrderService.class).count(new QueryWrapper().eq("aid", activity.getId()).eq("lotteryState", 1));
            return toSuccess(builder
                    .put("lottery", lottery)
                    .build());
        }
        if (activity.getType() == ActivityType.LOTTERY) {
            long totalLottery = this.dispatchContext.getServiceOne(ActivityLotteryOrderService.class).totalUserCount(activity.getId());
            long lottery = this.dispatchContext.getServiceOne(ActivityLotteryOrderService.class).count(new QueryWrapper().eq("aid", activity.getId()).eq("lotteryState", 1));
            builder.put("totalLottery", totalLottery)
                    .put("lottery", lottery)
            ; //抽奖参与人数

        }
        //浏览用户数量
        builder.put("preview", this.dispatchContext.getServiceOne(ActivityPreviewService.class).getPreview(activity.getId()));
        //新增用户数
        builder.put("totalUser", this.dispatchContext.getServiceOne(ShopUserService.class).totalByAid(activity.getId()));
        //总购买用户数
        builder.put("buyUser", this.dispatchContext.getServiceOne(ActivityOrderService.class).totalBuyUser(activity.getId()));
        builder.put("orderAmount", this.dispatchContext.getServiceOne(ActivityOrderService.class).totalMoney(activity.getId()));
        if (activity.getType() == ActivityType.SOLITAIRE)
            builder.put("solitaireRefund", this.dispatchContext.getServiceOne(ActivityOrderService.class).totalSumSolitaire(activity.getId()));//TODO 接龙返点
        return toSuccess(builder.build());

    }


    @GetMapping("/copy")
    public ResponseEntity copy(@RequestParam("id") long id, @RequestParam("shopId") long shopId) {
        Token<Object> token = TokenGet.get();
        this.dispatchContext.getServiceOne(ShopLinkUserService.class).verifyShop(token.getFid(), shopId);

        Activity activity = basicService.get(id);
        if (activity == null) return toError("活动不存在");
        if (activity.getShopId() != shopId) return toError("活动不存在");
        BasicEntity expand = this.dispatchContext.getServiceOne(ActivityFactory.class).get(activity.getType()).getByAid(activity.getId());

        ActivityInfoVo vo = activity.copy(new ActivityInfoVo());
        vo.setId(null);
        vo.setExpand(JSON.parseObject(expand.toJSONString()));
        vo.setTitle("复制 " + vo.getTitle());
        if (vo.getType() == ActivityType.LOTTERY) {
            vo.getExpand().put("items", this.dispatchContext.getServiceOne(ActivityLotteryItemService.class).findByAid(id));
        } else if (vo.getType() == ActivityType.VOTE) {
            List<ActivityVoteOther> others = this.dispatchContext.getServiceOne(ActivityVoteOtherService.class).findByAid(id);
            List<ActivityVoteItem> items = this.dispatchContext.getServiceOne(ActivityVoteItemService.class).findByAid(id);
            vo.getExpand().put("others", others);
            vo.getExpand().put("items", items);
        }

        ActivityOther other = this.dispatchContext.getServiceOne(ActivityOtherService.class).getByAid(id);
        if (other != null) {
            JSONObject object = JSON.parseObject(other.toJSONString());
            object.remove("id");
            vo.setOther(object);
        }
        return super.post(vo);
    }


    @ApiOperation(value = "最新抽奖记录", notes = "最新抽奖记录", nickname = "AdinZ")
    @GetMapping("/lottery-record")
    public ResponseEntity latestLottery(@RequestParam("size") int size,
                                        @RequestParam(value = "page", required = false, defaultValue = "1") int page,
                                        @RequestParam(value = "aid", required = false) Long aid,
                                        @RequestParam(value = "status", required = false) Integer status) {

        QueryWrapper wrapper = new QueryWrapper();

        wrapper.eq("lotteryState", status);
        wrapper.eq("aid", aid);
        ResponseEntity<List<ActivityLotteryOrder>> response = this.dispatchContext.getServiceOne(ActivityLotteryOrderService.class)
                .findPage(wrapper, PageRequest.of(page, size, Sort.Direction.DESC, "id"));
        List<JSONObject> collect = response.getData().stream().map(e -> {
            Object base = this.dispatchContext.getServiceOne(IUserService.class).fieldBase(e.getBuyerId());
            return JsonUtils.builder()
                    .put("user", base)
                    .put("title", e.getTitle())
                    .put("thumb", e.getThumb())
                    .put("price", e.getPrice())
                    .put("aid", e.getAid())
                    .put("oid", e.getOid())
                    .put("created", e.getCreated())
                    .build();
        }).collect(Collectors.toList());
        return toSuccess(collect, response.getTotal(), response.getTotalPage());
    }


    @GetMapping("/apply-record")
    public ResponseEntity applyRecord(@RequestParam("size") int size,
                                      @RequestParam(value = "page", required = false, defaultValue = "1") int page,
                                      @RequestParam(value = "aid", required = false) Long aid) {

        ResponseEntity<List<ActivityOrder>> response = this.dispatchContext.getServiceOne(ActivityOrderService.class).findPage(new QueryWrapper().eq("aid", aid)
                .eq("statusType", 1), PageRequest.of(page, size));
        List<JSONObject> collect = response.getData().stream().map(e -> {
            JSONObject object = JSON.parseObject(e.getOtherText());
            object.put("created", e.getCreated());
            object.put("user", this.dispatchContext.getServiceOne(IUserService.class).fieldBase(e.getBuyerId()));
            return object;
        }).collect(Collectors.toList());
        return toSuccess(collect, response.getTotal(), response.getTotalPage());
    }

    @GetMapping("/apply-record-down")
    public ResponseEntity applyRecordDown(@RequestParam(value = "aid", required = false) Long aid, HttpServletResponse response) throws IOException {
        List<ActivityOrder> orders = this.dispatchContext.getServiceOne(ActivityOrderService.class).findList(new QueryWrapper().eq("aid", aid).eq("statusType", 1));
        StringBuffer path = new StringBuffer(System.getProperty("user.dir")).append("/file/");
        Path path1 = Paths.get(path.toString());
        if (Files.notExists(path1)) {
            Files.createDirectory(path1);
        }
        String fileName = RandomUtils.randomSnowflake() + ".xlsx";
        path.append(fileName);
        FileOutputStream stream = new FileOutputStream(path.toString());
        try {
            EasyExcel.write(stream, ApplyRecordDownload.class).sheet("报名记录").doWrite(() -> orders.stream().map(e -> {
                ApplyRecordDownload d = new ApplyRecordDownload();
                JSONObject object = JSON.parseObject(e.getOtherText());
                d.setName(object.getString("name"));
                d.setApplyMobile(object.getString("mobile"));
                d.setAddress(object.getString("address"));
                d.setDate(DateUtils.format(e.getCreated()));
                d.setId(String.valueOf(e.getId()));
                return d;
            }).collect(Collectors.toList()));
            Object url = "/api-file/" + fileName;
            return toSuccess(url);
        } finally {
            stream.close();
        }
    }


    @ApiOperation(value = "封面模板", notes = "封面模板", nickname = "AdinZ")
    @GetMapping("/thumb-list")
    public ResponseEntity thumbList(@RequestParam("type") ActivityType type) {
        return toSuccess(Shopkeeper.getActivityThumbTemplate(type));
    }


}
